#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<string.h>

void printSigset(sigset_t *sigset)
{
	int sig;
	int cnt = 0;
	/* NSIG = 65 */
	for (sig = 1; sig < NSIG; sig++)
	{
		if (sigismember(sigset, sig))
		{
			cnt++;
			printf("%s\n",strsignal(sig));
		}
	}
	if (cnt == 0)
		printf("<empty signal set>\n");
}

/* 获取进程的信号阻塞掩码 
 * int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
 * how指定动作， set为我们指定的信号集， oldset返回原有的信号集。
 * 当how == SIG_BLOCK时   原有阻塞信号集 + set指定的信号集， 构成新的阻塞信号集
 * 当how == SIG_UNBLOCK时 原有阻塞信号集 - set指定的信号集， 构成新的阻塞信号集
 * 当how == SIG_SETMASK时 由set指定的信号集 代替 原有阻塞信号集， 构成新的阻塞信号集
 *
 * sigprocmask(SIG_BLOCK, NULL, &oldset); 获取当前进程的信号阻塞掩码，当set为NULL时，将忽略how
 * sigprocmask(sigprocmask, set, NULL);   增加set里面的信号到当前进程的信号阻塞掩码中.
 *
 * */
int print_process_sigmask()
{
	sigset_t mask;
	if (sigprocmask(SIG_BLOCK, NULL, &mask) == -1)
		return -1;
	printSigset(&mask);
	return 0;
}

/* 获取进程pending的信号集 */
int print_pending_sig()
{
	sigset_t pending;
	if (sigpending(&pending) == -1)
		return -1;
	printSigset(&pending);
	return 0;
}

/*
 * sigset_t 用来代表一个信号集合
 * int sigemptyset(sigset_t *set) 清空信号集set里的所有信号
 * int sigfillset(sigset_t *set)  在信号集set里填充所有信号
 * int sigaddset(sigset_t *set,int sig) 在set增加sig
 * int sigdelset(sigset_t *set,int sig) 在set减少sig
 * int sigismember(const sigset_t *set,int sig) 判断sig是否属于set
 * int sigandset(sigset_t *set,sigset_t *left,sigset_t *right); 交集
 * int sigorset(sigset_t *set,sigset_t *left,sigset_t *right); 并集
 * int sigisemptyset(const sigset_t *set) 判断是否空集
 *
 * */
void sig_cont(int signo)
{
	if (signo == SIGCONT)
	{
		printf("catch SIGCONT\n");
	}
}

int main()
{
	/* 为SIGCONT安装处理函数 */
	signal(SIGCONT, sig_cont);

	printf("process signal mask:\n");
	print_process_sigmask();
	
	sigset_t mask;
	sigemptyset(&mask);
	sigaddset(&mask, SIGCONT);
	/* 增加SIGCONT到进程的signal mask */
	sigprocmask(SIG_BLOCK, &mask, NULL);
	
	printf("process signal mask:\n");
	print_process_sigmask();
	
	printf("process pending signal:\n");
	print_pending_sig();
	/* 给自身发送SIGCONT信号 */
	/* 发送2次 */
	raise(SIGCONT);
	raise(SIGCONT);
	
	printf("process pending signal:\n");
	print_pending_sig();

	/* 清空阻塞掩码 */
	sigemptyset(&mask);
	sigprocmask(SIG_SETMASK, &mask, NULL);
	return 0;
}
